﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Tools/IEHelper 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       IEHelper
* 创建时间：  2025/6/4 15:13:51
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SSPivot.AspNetCore.Abstractions.User;
using SSPivot.Common.Cache;
using SSPivot.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Magicodes.ExporterAndImporter.Excel;
using Magicodes.ExporterAndImporter.Excel.AspNetCore;
using Magicodes.ExporterAndImporter.Core.Models;

namespace SSPivot.Tools
{
    /// <summary>
    /// 导入导出帮助类
    /// </summary>
    public class IEHelper
    {
        private readonly ICurrentUser _user;
        private readonly ICacheService _cache;

        public IEHelper(
            ICurrentUser user,
            ICacheService cache)
        {
            _user = user;
            _cache = cache;
        }

        /// <summary>
        /// 下载模板
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<ActionResult> DownloadTemplateAsync<T>(T type, string fileName) where T : class, new()
        {
            var result = await new ExcelImporter().GenerateTemplateBytes<T>();
            return new XlsxFileResult(result, fileName);
        }

        /// <summary>
        /// 下载错误标记文件
        /// </summary>
        /// <param name="fileId"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<ActionResult> DownloadErrorMarkAsync(string fileId, string fileName)
        {
            var excelErrorMarkKey = GlobalConfigTool.CacheKeys.GetExcelErrorMarkKey(_user.Id ?? 0, fileId);
            var fileStream = await _cache.GetAsync<byte[]>(excelErrorMarkKey);
            await _cache.RemoveAsync(excelErrorMarkKey);
            if (fileStream == null)
            {
                throw ServiceResult.Exception("请重新导入数据，再下载错误标记文件", statusCode: 500);
            }

            if (fileName.IsNull())
            {
                fileName = $"错误标记文件{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx";
            }

            return new XlsxFileResult(fileStream, fileName);
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        /// <param name="dataItems"></param>
        /// <param name="fileName"></param>
        /// <param name="sheetName"></param>
        /// <returns></returns>

        public async Task<ActionResult> ExportDataAsync<T>(ICollection<T> dataItems, string fileName = null, string sheetName = null) where T : class, new()
        {
            var result = await new ExcelExporter().Append(dataItems, sheetName).ExportAppendDataAsByteArray();

            if (fileName.IsNull())
            {
                fileName = $"数据列表{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx";
            }

            return new XlsxFileResult(result, fileName);
        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="file"></param>
        /// <param name="fileId"></param>
        /// <param name="importResultCallback"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ImportResult<T>> ImportDataAsync<T>(IFormFile file, string fileId, Func<ImportResult<T>, Task<ImportResult<T>>> importResultCallback = null) where T : class, new()
        {
            var importResult = await new ExcelImporter().Import<T>(file.OpenReadStream());

            if (importResultCallback != null)
            {
                importResult = await importResultCallback(importResult);
            }

            var errorMsg = new StringBuilder();
            if (importResult != null && importResult.HasError)
            {
                if (importResult.Exception != null)
                {
                    errorMsg.AppendLine("错误信息：");
                    errorMsg.AppendLine(importResult.Exception.Message);
                }

                if (importResult.TemplateErrors != null && importResult.TemplateErrors.Count > 0)
                {
                    errorMsg.AppendLine("缺少数据列：" + string.Join("，", importResult.TemplateErrors.Select(m => m.RequireColumnName).ToList()));
                }
            }

            var rowErros = importResult.RowErrors;
            if (rowErros?.Count > 0)
            {
                errorMsg.AppendLine("数据填写有误：");
                rowErros = rowErros.OrderBy(a => a.RowIndex).ToList();
                foreach (DataRowErrorInfo drErrorInfo in rowErros)
                {
                    foreach (var item in drErrorInfo.FieldErrors)
                    {
                        errorMsg.AppendLine($"第{drErrorInfo.RowIndex}行 - {item.Key}：{item.Value}");
                    }
                }

                //缓存错误标记文件
                new ExcelImporter().OutputBussinessErrorData<T>(file.OpenReadStream(), rowErros.ToList(), out byte[] fileByte);
                var userId = _user.Id;
                await _cache.RemoveAsync(GlobalConfigTool.CacheKeys.GetExcelErrorMarkKey(userId ?? 0, fileId));
                await _cache.SetAsync(GlobalConfigTool.CacheKeys.GetExcelErrorMarkKey(userId ?? 0, fileId), fileByte, TimeSpan.FromMinutes(20));
            }

            if (errorMsg.Length > 0)
            {
                throw ServiceResult.Exception(errorMsg.ToString());
            }

            return importResult;
        }
    }
}
